using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Collections;
using System.Diagnostics;
using NovodexWrapper;

/// <summary>
/// Summary description for Class1
/// </summary>
/// 

namespace marbletrack
{
    public class Support
    {
        private const int DIVISIONS = 15;
        internal Vector3 modelPosition_;
        VertexPositionNormalTexture[] pointList = new VertexPositionNormalTexture[DIVISIONS * 2 + 2];
        int[] lineListIndices = new int[DIVISIONS * 6];
        internal int flashCountdown = 20;
        public NxActor Actor;
        public TrackPiece TrackPiece;

        VertexDeclaration vertexDeclaration;

        public Support(TrackPiece trackPiece)
        {
            TrackPiece = trackPiece;
            modelPosition_ = trackPiece.ModelPosition;

            //Create the vertex buffer (pointList) with the correct texture coordinates
            Vector3 temp1 = modelPosition_;
            temp1.Y = modelPosition_.Y - (Game1.HALFSQUARESIZE / 2);
            Vector3 temp2 = modelPosition_;
            temp2.Y = -10;
            int i = 0;
            for (double x = 0; x <= 2 * Math.PI; x += 2 * Math.PI / DIVISIONS)
            {
                pointList[i].Position = temp1;
                pointList[i].Position.X += (float)(Game1.HALFSQUARESIZE * Math.Cos(x) * 0.25);
                pointList[i].Position.Z += (float)(Game1.HALFSQUARESIZE * Math.Sin(x) * 0.25);
                pointList[i].TextureCoordinate = new Vector2((i / 2.0f) / DIVISIONS, 0.0f);
                i++;
                pointList[i].Position = temp2;
                pointList[i].Position.X += (float)(Game1.HALFSQUARESIZE * Math.Cos(x));
                pointList[i].Position.Z += (float)(Game1.HALFSQUARESIZE * Math.Sin(x));
                pointList[i].TextureCoordinate = new Vector2(((i - 1.0f) / 2.0f) / DIVISIONS, 1.0f);
                i++;
            }

            //calculates the values for the index buffer
            int j = 0;
            for (int k = 0; k < lineListIndices.Length; k += 6)
            {
                //triangle 1 (first triangle in a quad)
                lineListIndices[k] = j;
                lineListIndices[k + 1] = j + 1;
                lineListIndices[k + 2] = j + 3;
                //triangle 2 (second triangle in a quad)
                lineListIndices[k + 3] = j + 2;
                lineListIndices[k + 4] = j;
                lineListIndices[k + 5] = j + 3;
                j += 2;
            }

            //Generate normals
            for (int k = 0; k < lineListIndices.Length / 3; k++)
            {
                Vector3 firstvec = pointList[lineListIndices[k * 3 + 1]].Position - pointList[lineListIndices[k * 3]].Position;
                Vector3 secondvec = pointList[lineListIndices[k * 3]].Position - pointList[lineListIndices[k * 3 + 2]].Position;
                Vector3 normal = Vector3.Cross(firstvec, secondvec);
                normal.Normalize();
                pointList[lineListIndices[k * 3]].Normal += normal;
                pointList[lineListIndices[k * 3 + 1]].Normal += normal;
                pointList[lineListIndices[k * 3 + 2]].Normal += normal;
            }
            Vector3 tempNormal = pointList[0].Normal;
            pointList[0].Normal += pointList[pointList.Length - 2].Normal;
            pointList[pointList.Length - 2].Normal += tempNormal;
            tempNormal = pointList[1].Normal;
            pointList[1].Normal += pointList[pointList.Length - 1].Normal;
            pointList[pointList.Length - 1].Normal += tempNormal;
            for (int k = 0; k < pointList.Length; k++)
            {
                pointList[k].Normal.Normalize();
            }

            Actor = Game1.GetPhysics.CreateTriangleMeshActor(pointList, lineListIndices, Matrix.Identity, Physics.TRACK_SUPPORT_PHYSICS_GROUP, true, true);

            //Vertex Declaration
            vertexDeclaration = new VertexDeclaration(Game1.Graphics.GraphicsDevice, VertexPositionNormalTexture.VertexElements);
        }

        //Perform overlap testing to check for overlaps with track pieces
        public bool Overlaps()
        {
            NxBounds3 worldBounds = Actor.getFirstShape().getWorldBounds();
            worldBounds.fatten(-30f); //shrink the bounding box by a small amount so collisions aren't reported for objects which are right next to each other
            for (int i = 0; i < Game1.modelList.Count; i++)
            {
                TrackPiece trackpiece = (TrackPiece)Game1.modelList[i];
                foreach (NxShape shape in trackpiece.Actor.getShapes())
                {
                    if (shape.checkOverlapAABB(worldBounds))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        //Draw the support using XNA's primitive types
        public void Draw()
        {
            if (flashCountdown % 2 == 0)//flashes/blinks support when created
            {
                Game1.Graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration;

                Game1.basicEffect.View = Game1.view;
                Game1.basicEffect.Projection = Game1.projectionMatrix;
                Game1.basicEffect.Texture = Game1.supportTexture;
                //Game1.basicEffect.FogEnabled = true;
                Game1.basicEffect.Begin();

                foreach (EffectPass pass in Game1.basicEffect.CurrentTechnique.Passes)
                {
                    pass.Begin();

                    Game1.Graphics.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,
                        pointList, 0, pointList.Length, lineListIndices, 0, lineListIndices.Length / 3);

                    pass.End();
                }
                Game1.basicEffect.End();
            }
            if (flashCountdown > 0)
            { flashCountdown--; }
        }
    }
}